package com.cman777.springc.idempotence.storage;

import com.cman777.springc.idempotence.ResultWrapper;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;

import java.io.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author chenzhicong
 * @time 2020/9/15 10:55
 */
@Log4j2
public class RedissionStorageAdapter implements Storage {
    private Long cacheTime;
    private RedissonClient redissonClient;

    public RedissionStorageAdapter(RedissonClient redissonClient, Long cacheTime) {
        this.redissonClient = redissonClient;
        this.cacheTime = cacheTime;
    }

    @Override
    public boolean setIfAbsent(String key, Supplier<ResultWrapper> supplier) {
        if (this.exists(key)) {
            return false;
        } else {
            return this.setIfAbsent(key, supplier.get());
        }
    }

    @Override
    public boolean setIfAbsent(String key, ResultWrapper value) {
        String valueStr = null;
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             ObjectOutputStream out = new ObjectOutputStream(byteArrayOutputStream)) {
            out.writeObject(value);
            byte[] exceptionBytes = byteArrayOutputStream.toByteArray();
            valueStr = Base64.encodeBase64String(exceptionBytes);
            log.info(valueStr.length());
        } catch (Exception ex) {
            log.error("序列化错误", ex);
            return false;
        }
        if (cacheTime == null) {
            return redissonClient.getBucket(key).trySet(valueStr);
        } else {
            return redissonClient.getBucket(key).trySet(valueStr, cacheTime, TimeUnit.SECONDS);
        }

    }

    @Override
    public boolean delete(String idempotenceId) {
        return redissonClient.getBucket(idempotenceId).delete();
    }

    @Override
    public <T extends Serializable> ResultWrapper<T> getResult(String idempotenceId) {
        ResultWrapper<T> resultWrapper = null;

        String value = (String)redissonClient.getBucket(idempotenceId).get();
        if (StringUtils.isBlank(value)) {
            return null;
        }
        try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(Base64.decodeBase64(value)))) {
            resultWrapper = (ResultWrapper<T>) ois.readObject();
        } catch (Exception e) {
            log.error("反序列化错误", e);
        }
        return resultWrapper;
    }

    @Override
    public boolean exists(String key) {
        return redissonClient.getBucket(key).isExists();
    }
}
